package guitplugin;

import com.sun.mirror.type.AnnotationType;
import com.sun.mirror.type.ArrayType;
import com.sun.mirror.type.ClassType;
import com.sun.mirror.type.DeclaredType;
import com.sun.mirror.type.EnumType;
import com.sun.mirror.type.InterfaceType;
import com.sun.mirror.type.PrimitiveType;
import com.sun.mirror.type.ReferenceType;
import com.sun.mirror.type.TypeMirror;
import com.sun.mirror.type.TypeVariable;
import com.sun.mirror.type.VoidType;
import com.sun.mirror.type.WildcardType;
import com.sun.mirror.util.TypeVisitor;

import java.util.Collection;

public class QualifiedNameVisitor implements TypeVisitor {

  private String qualifiedName;

  private final boolean allowPrimitives;

  public QualifiedNameVisitor(boolean allowPrimitives) {
    this.allowPrimitives = allowPrimitives;
  }

  private void visitType(DeclaredType type) {
    qualifiedName = type.getDeclaration().getQualifiedName();
    Collection<TypeMirror> arguments = type.getActualTypeArguments();
    if (arguments.size() > 0) {
      StringBuilder sb = new StringBuilder();
      for (TypeMirror typeMirror : arguments) {
        if (sb.length() > 0) {
          sb.append(", ");
        }

        QualifiedNameVisitor visitor = new QualifiedNameVisitor(allowPrimitives);
        typeMirror.accept(visitor);
        sb.append(visitor.getQualifiedName());
      }
      qualifiedName += "<" + sb.toString() + ">";
    }
  }

  @Override
  public void visitAnnotationType(AnnotationType type) {
    visitType(type);
  }

  @Override
  public void visitArrayType(ArrayType type) {
  }

  @Override
  public void visitClassType(ClassType type) {
    visitType(type);
  }

  @Override
  public void visitDeclaredType(DeclaredType type) {
    visitType(type);
  }

  @Override
  public void visitEnumType(EnumType type) {
    visitType(type);
  }

  @Override
  public void visitInterfaceType(InterfaceType type) {
    visitType(type);
  }

  @Override
  public void visitPrimitiveType(PrimitiveType type) {
    String primitive = type.getKind().name().toLowerCase();
    if (allowPrimitives) {
      qualifiedName = primitive;
    } else {
      if (primitive.equals("int")) {
        primitive = "integer";
      } else if (primitive.equals("char")) {
        primitive = "character";
      }
      qualifiedName =
          "java.lang." + primitive.substring(0, 1).toUpperCase() + primitive.substring(1);
    }
  }

  @Override
  public void visitReferenceType(ReferenceType type) {
  }

  @Override
  public void visitTypeMirror(TypeMirror type) {
  }

  @Override
  public void visitTypeVariable(TypeVariable type) {
  }

  @Override
  public void visitVoidType(VoidType type) {
    if (allowPrimitives) {
      qualifiedName = "void";
    } else {
      qualifiedName = "java.lang.Void";
    }
  }

  @Override
  public void visitWildcardType(WildcardType type) {
    throw new RuntimeException("wildcard");
  }

  public String getQualifiedName() {
    return qualifiedName;
  }

  public String getQualifiedNameWithoutParameters() {
    String q = qualifiedName;
    int indexOf = q.indexOf("<");
    if (indexOf != -1) {
      q = q.substring(0, indexOf);
    }
    return q;
  }
}
